package com.wangijun.yuan.web.service;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.wangijun.yuan.core.domain.OperateInfo;
import com.wangijun.yuan.core.model.em.OperateTypeEnum;
import com.wangijun.yuan.web.mapper.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author readpage
 * @since 2023-02-03 16:15
 */
@Service
@RequiredArgsConstructor
public class OperateInfoService extends ServiceImpl<OperateInfoMapper, OperateInfo> {
    private final CommentMapper commentMapper;
    private final ArticleMapper articleMapper;
    private final UserInfoMapper userInfoMapper;
    private final TagInfoMapper tagInfoMapper;
    private final TopicInfoMapper topicInfoMapper;
    


    private NoticeEventService getNoticeEventService() {
        return SpringUtil.getBean(NoticeEventService.class);
    }
    
    /**
     * 功能描述: 获取登录用户点赞的评论ID
     *
     * @author wlf 2024/6/28 10:35
     */
    public List<Long> getCommentIds() {
        if (!StpUtil.isLogin()) {
            return List.of();
        }
        Long userid = StpUtil.getLoginIdAsLong();
        // Mysql中的点赞的评论
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getUserId, userid)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.comment_like.getCode())
                .list().stream().map(OperateInfo::getDataId).toList();
    }

    /**
     * 功能描述: 获取点赞文章IDS
     *
     * @author wlf 2024/6/28 10:38
     */
    public List<Long> getStarArticleIds() {
        if (!StpUtil.isLogin()) {
            return List.of();
        }
        return getStarArticleIds(StpUtil.getLoginIdAsLong());
    }

    /**
     * 功能描述: 获取收藏文章IDs
     *
     * @author wlf 2024/6/28 10:38
     */
    public List<Long> getFavArticleIds() {
        if (!StpUtil.isLogin()) {
            return List.of();
        }
        return getFavArticleIds(StpUtil.getLoginIdAsLong());
    }

    /**
     * 功能描述: 获取点赞文章IDS
     *
     * @author wlf 2024/6/28 10:38
     */
    public List<Long> getStarArticleIds(Long userId) {
        // Mysql中的点赞的评论
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getUserId, userId)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.article_like.getCode())
                .list().stream().map(OperateInfo::getDataId).toList();
    }

    /**
     * 功能描述: 获取收藏文章IDs
     *
     * @author wlf 2024/6/28 10:38
     */
    public List<Long> getFavArticleIds(Long userId) {
        // Mysql中的点赞的评论
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getUserId, userId)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.article_fav.getCode())
                .list()
                .stream()
                .map(OperateInfo::getDataId).toList();
    }

    /**
     * 功能描述: 获取关注标签IDs
     *
     * @author wlf 2024/6/28 10:38
     */
    public List<Long> getFollowTagIds() {
        if (!StpUtil.isLogin()) {
            return List.of();
        }
        return getFollowTagIds(StpUtil.getLoginIdAsLong());
    }


    public List<Long> getFollowTagIds(Long userId) {
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getUserId, userId)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.tag_follow.getCode())
                .list()
                .stream()
                .map(OperateInfo::getDataId).toList();
    }

    /**
     * 功能描述: 获取关注标签IDs
     *
     * @author wlf 2024/6/28 10:38
     */
    public List<Long> getFollowTopicIds() {
        if (!StpUtil.isLogin()) {
            return List.of();
        }
        return getFollowTopicIds(StpUtil.getLoginIdAsLong());
    }


    public List<Long> getFollowTopicIds(Long userId) {
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getUserId, userId)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.topic_follow.getCode())
                .list()
                .stream()
                .map(OperateInfo::getDataId).toList();
    }


    /**
     * 功能描述: 获取关注用户IDs
     *
     * @author wlf 2024/6/29 11:03
     */
    public List<Long> getFollowUserIds() {
        if (!StpUtil.isLogin()) {
            return List.of();
        }
        Long userid = StpUtil.getLoginIdAsLong();
        return getFollowUserIds(userid);
    }

    /**
     * 功能描述: 获取关注用户IDs
     *
     * @author wlf 2024/6/29 11:03
     */
    public List<Long> getFollowUserIds(Long userid) {
        // Mysql中的点赞的评论
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getUserId, userid)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.user_follow.getCode())
                .list()
                .stream()
                .map(OperateInfo::getDataId).toList();
    }

    /**
     * 功能描述: 获取粉丝用户IDs
     * 有点绕,但总体逻辑没错
     *
     * @author wlf 2024/6/29 11:03
     */
    public List<Long> getFansUserIds(Long userid) {
        // 收藏文章
        // Mysql中的点赞的评论
        return Db.lambdaQuery(OperateInfo.class)
                .eq(OperateInfo::getDataId, userid)
                .eq(OperateInfo::getOperateType, OperateTypeEnum.user_follow.getCode())
                .list()
                .stream()
                .map(OperateInfo::getUserId).toList();
    }

    /**
     * 功能描述: 继续抽象，写个代码，我自己感觉都抽象起来了。
     *
     * @author wlf 2024/6/28 19:48
     */
    @Transactional
    public boolean operate(OperateTypeEnum typeEnum, Long dataId) {
        StpUtil.checkLogin();
        try {
            long userId = StpUtil.getLoginIdAsLong();
            // 查询一下数据库
            OperateInfo one = Db.lambdaQuery(OperateInfo.class)
                    .eq(OperateInfo::getUserId, userId)
                    .eq(OperateInfo::getOperateType, typeEnum.getCode())
                    .eq(OperateInfo::getDataId, dataId)
                    .one();
            int num;
            if (one == null) {
                this.save(OperateInfo.builder()
                        .userId(userId)
                        .dataId(dataId)
                        .operateType(typeEnum)
                        .build());
                num = 1;
            } else {
                this.removeById(one.getId());
                num = -1;
            }
            switch (typeEnum) {
                case article_fav -> {
                    articleMapper.favoritesAdd(dataId, num);

                    getNoticeEventService().favArt(userId, dataId, num);

                }
                case article_like -> {
                    articleMapper.starAdd(dataId, num);
                    getNoticeEventService().likedArt(userId, dataId, num);
                }
                case comment_like -> {
                    commentMapper.likedAdd(dataId, num);

                    getNoticeEventService().likedComment(userId, dataId, num);

                }
                case user_follow -> {
                    userInfoMapper.fansNumAdd(dataId, num);
                    userInfoMapper.favNumAdd(userId, num);
                    SpringUtil.getBean(UserService.class).cacheEvict(userId);
                    SpringUtil.getBean(UserService.class).cacheEvict(dataId);

                    getNoticeEventService().followUser(userId, dataId, num);

                }
                case tag_follow -> {
                    tagInfoMapper.followNumAdd(dataId, num);

                    getNoticeEventService().tagFollow(dataId, num);
                }
                case topic_follow -> {
                    topicInfoMapper.followNumAdd(dataId, num);

                    getNoticeEventService().topicFollow(dataId, num);
                }
            }
            return one == null;
        } catch (Exception e) {
            throw new RuntimeException("操作异常");
        }

    }
}
